#include "../server_deps.h"
#include "../server.h"
#include "../server_console.h"

#include "share/util.h"


#include "proto_mgr.h"

#include <regex>
#include <stdarg.h>
#include <fstream>

using namespace std;

template<typename ProtoT>
bool load_map_one(ProtoMapT<ProtoT> &proto_map, const char* file, MapIniterT<ProtoT> initer) {
    bool is_ok = true;

    Json::Value json;
    const char* path = fmt_cstr("%s/res/%s", get_deploy(), file);
    json = to_json(load_file(path));
    if (json.empty()) {
        UTIL_LOG(E, "%s load error", path);
        is_ok = false;
    }

    const Json::Value &items = json["item"];
    if (items.empty()) {
        UTIL_LOG(E, "%s empty", path);
    }

    for (auto itr = items.begin(); itr != items.end(); ++itr) {
        ProtoT proto;
        const Json::Value &item = *itr;
        bool insert = true;
        bool res = initer(proto, item, insert);

        if (!res) {
            UTIL_LOG(E, "file %s proto %d init failed", file, proto.id);
        }

        if (proto.id < 0) {
            UTIL_LOG(E, "file %s invalid id %d", file, proto.id);
            is_ok = false;
            continue;
        }

        if (!insert)
            continue;

        if (proto_map.count(proto.id) > 0) {
            UTIL_LOG(E, "file %s error %d already exist", file, proto.id);
            is_ok = false;
            continue;
        }

        proto_map[proto.id] = proto;
    }

    //UTIL_LOG(I, "file %s init %s", file, is_ok ? "ok" : "fail");
    return is_ok;
}


template<typename ProtoT>
bool load_arr_one(ProtoArrT<ProtoT> &proto_arr, const char* file, ArrIniterT<ProtoT> initer) {
    bool is_ok = true;

    Json::Value json;
    const char* path = fmt_cstr("%s/res/%s", get_deploy(), file);
    json = to_json(load_file(path));
    if (json.empty()) {
        UTIL_LOG(E, "%s load error", path);
        is_ok = false;
    }

    const Json::Value &items = json["item"];
    if (items.empty()) {
        UTIL_LOG(E, "%s empty", path);
    }

    for (auto itr = items.begin(); itr != items.end(); ++itr) {
        ProtoT proto;
        const Json::Value &item = *itr;

        bool res = initer(proto, item);

        if (!res) {
            UTIL_LOG(E, "file %s proto %d init failed", file, proto.id);
        }

        if (proto.id < 0) {
            continue;
        }
        if (proto_arr.size() != proto.id) {
            UTIL_LOG(E, "file %s error %d no continue", file, proto.id);
            is_ok = false;
            continue;
        }
        proto_arr.emplace_back(proto);
    }

    UTIL_LOG(T, "file %s init %s", file, is_ok ? "ok" : "fail");
    return is_ok;
}


void ProtoMgr::destroy() {
#define UNLOAD_MAP(name) \
        _mapProto##name.clear()
#define UNLOAD_ARR(name) \
        _arrProto##name.clear()

    // 3
    UNLOAD_MAP(Pet);
    UNLOAD_MAP(Character);
    UNLOAD_MAP(Skill);
    UNLOAD_MAP(SkillSet);
    UNLOAD_MAP(Buff);
    UNLOAD_MAP(Sprite);
    UNLOAD_MAP(SpriteSkill);
    UNLOAD_MAP(AttMod);
    UNLOAD_MAP(Value);
    UNLOAD_MAP(Level);
    UNLOAD_MAP(Item);
    UNLOAD_MAP(Consume);
    UNLOAD_MAP(Reward);
    UNLOAD_MAP(BossLevel);
    UNLOAD_MAP(EncounterItem);
    UNLOAD_MAP(Encounter);
    UNLOAD_MAP(Explore);
    UNLOAD_MAP(RandSet);
    UNLOAD_MAP(Task);
    UNLOAD_MAP(Charge);

    UNLOAD_ARR(EquipLevel);
    UNLOAD_ARR(PetLevel);
    UNLOAD_ARR(PetRearConsume);
    UNLOAD_ARR(PetQuality);
    UNLOAD_ARR(EggRandom);
    UNLOAD_ARR(Medal);
    UNLOAD_ARR(Star);
    UNLOAD_ARR(SpriteQuality);
    UNLOAD_ARR(SpriteSkillLevel);
    UNLOAD_ARR(PetStar);
    UNLOAD_ARR(ComposeStone);
    UNLOAD_ARR(PetFamily);
    UNLOAD_ARR(MagicLevel);
    UNLOAD_ARR(ArenaReward);
    UNLOAD_ARR(Alive);
    UNLOAD_ARR(AliveReward);
    UNLOAD_ARR(MoneyGet);
    UNLOAD_ARR(AccChargeReward);
    UNLOAD_ARR(WorldBossReward);
    UNLOAD_ARR(TrainReward);
    UNLOAD_ARR(Floor);
    UNLOAD_ARR(PetFriendStage);
    UNLOAD_ARR(SpriteFormLevel);
    UNLOAD_ARR(Pointrank);
    UNLOAD_ARR(CardReward);

    UTIL_LOG(I, "ProtoMgr销毁");

#undef UNLOAD_MAP
#undef UNLOAD_ARR
}

#define CHECK_FIELD(type, field)    \
    {    \
        const void* ptr = MAProto(type, proto.field);    \
        if (proto.field >= 0 && NULL == ptr) {    \
            UTIL_LOG(E, "id:%d field:%s tagProto%s:%d not exist", proto.id, #field, #type, proto.field);    \
            ok = false;    \
        }    \
    }


bool ProtoMgr::check() {
#define CHECK_FVALUE(cond, fieldname, value)   \
        if (!(cond)) { \
             UTIL_LOG(E, "id:%d field:%s value:%f error\n", proto.id, fieldname, value);    \
             ok = false;    \
        }
#define CHECK_NVALUE(cond, fieldname, value)   \
        if (!(cond)) { \
             UTIL_LOG(E, "id:%d field:%s value:%d error\n", proto.id, fieldname, value);    \
             ok = false;    \
        }
#define CHECK_MAProto(type, protoid, fieldname) \
        if (protoid >= 0 && NULL == MAProto(type, protoid)) {    \
            UTIL_LOG(E, "id:%d field:%s type:%s proto:%d error\n", proto.id, fieldname, #type, protoid); \
            ok = false; \
        }
#define CHECK_ARProto(type, protoid, fieldname) \
        if (protoid >= 0 && NULL == ARProto(type, protoid)) {    \
            UTIL_LOG(E, "id:%d field:%s type:%s proto:%d error\n", proto.id, fieldname, #type, protoid); \
            ok = false; \
        }

#define CHECK_MAP_BEGIN(type)   {   \
        const char* __name = #type;\
        int num = 0;    \
        for (auto itr = _mapProto##type.begin(); itr != _mapProto##type.end(); ++itr, ++num) {  \
            bool ok = true;\
            const tagProto##type &proto = itr->second;  \
            if (proto.id < 0) {  \
                UTIL_LOG(E, "con:%s id:%d is invalid\n", #type, proto.id);   \
                ok = false; \
            }
#define CHECK_MAP_END()   \
        if (!ok) {\
            UTIL_LOG(E, "con:%s id:%d is invalid\n", __name, proto.id);   \
            gok = false; \
        }}}
#define CHECK_ARR_BEGIN(type) { \
        const char* __name = #type;\
        int num = 0;    \
        for (auto itr = _arrProto##type.begin(); itr != _arrProto##type.end(); ++itr, ++num) {    \
            bool ok = true;\
            const tagProto##type &proto = *itr;   \
            if (proto.id != num) {  \
                UTIL_LOG(E, "con:%s id:%d is not equal array index\n", #type, proto.id);   \
                ok = false; \
            }
#define CHECK_ARR_END() \
        if (!ok) {\
            UTIL_LOG(E, "con:%s id:%d is invalid\n", __name, proto.id);   \
            gok = false; \
        }}}


    bool gok = true;

    CHECK_MAP_BEGIN(Pet)
        //CHECK_NVALUE(proto.cardid >= 0 && set_cardid.count(proto.cardid) == 0, "cardid", proto.cardid);
        CHECK_MAProto(Character, proto.character, "character");
        CHECK_NVALUE(EPetProperty_IsValid(proto.family), "family", proto.family);
        CHECK_NVALUE(EQuality_IsValid(proto.quality), "quality", proto.quality);
        CHECK_MAProto(Reward, proto.release_reward, "release_reward");
        CHECK_NVALUE(proto.stage >= 1 && proto.stage <= 3, "stage", proto.stage);
        CHECK_MAProto(Item, proto.evo_itemid, "evo_itemid");
        CHECK_NVALUE(proto.max_normalskill_num <= PetNormalSkillNum, "max_normalskill_num", proto.max_normalskill_num);
        CHECK_NVALUE(proto.def_normalskill_num >= 0 && proto.def_normalskill_num <= proto.max_normalskill_num, "def_normalskill_num", proto.def_normalskill_num);
        CHECK_NVALUE(proto.potent_point <= 200, "potent_point", proto.potent_point);
        CHECK_MAProto(Pet, proto.evolve_to, "evolve_to");
        CHECK_MAProto(AttMod, proto.attmod, "attmod");
        CHECK_NVALUE(proto.mutate_family < 0 || EPetProperty_IsValid(proto.mutate_family), "mutate_family", proto.mutate_family);
        for (int i=0; i<2; ++i)
            CHECK_MAProto(Skill, proto.skill[i], fmt_cstr("skill%d", i+1));
        CHECK_MAProto(SkillSet, proto.skill_set, "skill_set");
        for (int i=0; i<PetAptitudeNum; ++i)
            CHECK_NVALUE(proto.aptitude[i] > 0, fmt_cstr("max_aptitude%d", i+1), proto.aptitude[i]);
    CHECK_MAP_END()

    CHECK_MAP_BEGIN(Character)
        CHECK_NVALUE(proto.random >= 0 && proto.random <= 2, "random", proto.random);
    CHECK_MAP_END()

    CHECK_ARR_BEGIN(Medal)
    	CHECK_NVALUE(proto.maxpower_add >= 0, "maxpower_add", proto.maxpower_add);
    	CHECK_NVALUE(proto.group >= 0, "group", proto.group);
    	CHECK_MAProto(AttMod, proto.attmod, "attmod");
    	CHECK_NVALUE(proto.task_page >= 0, "task_page", proto.task_page);

    CHECK_ARR_END()

    CHECK_MAP_BEGIN(SkillSet)
        int skill_num = proto.item.size();
        for (int i=0; i<skill_num; ++i)
            CHECK_MAProto(Skill, proto.item[i].first, fmt_cstr("skill%d", i+1));
    CHECK_MAP_END()

    CHECK_MAP_BEGIN(Skill)
        CHECK_NVALUE(proto.family < 0 || EPetProperty_IsValid(proto.family), "family", proto.family);

        CHECK_MAProto(AttMod,   proto.caster_attmodid      , "caster_attmodid"      );
        CHECK_MAProto(Buff,     proto.caster_buffid        , "caster_buffid"        );
        CHECK_MAProto(Value,    proto.caster_damage_valueid, "caster_damage_valueid");
        CHECK_MAProto(Value,    proto.caster_heal_valueid  , "caster_heal_valueid"  );

        CHECK_MAProto(AttMod, proto.target_attmodid      , "target_attmodid"          );
        CHECK_MAProto(Buff,   proto.target_buffid        , "target_buffid"            );
        CHECK_MAProto(Value,  proto.target_damage_valueid, "target_damage_valueid"    );
        CHECK_MAProto(Value,  proto.target_heal_valueid  , "target_heal_valueid"      );

    CHECK_MAP_END()

    CHECK_MAP_BEGIN(Buff)
        CHECK_MAProto(AttMod, proto.attmodid      , "attmodid"      );
        CHECK_MAProto(Value,  proto.damage_valueid, "damage_valueid");
        CHECK_MAProto(Value,  proto.heal_valueid  , "heal_valueid"  );
    CHECK_MAP_END()

    CHECK_MAP_BEGIN(Sprite)
        CHECK_MAProto(SpriteSkill, proto.skill[0], "skill[0]");
        CHECK_MAProto(SpriteSkill, proto.skill[1], "skill[1]");
        CHECK_MAProto(SpriteSkill, proto.skill[2], "skill[2]");
        CHECK_MAProto(SpriteSkill, proto.skill[3], "skill[3]");
        CHECK_MAProto(SpriteSkill, proto.skill[4], "skill[4]");
        CHECK_NVALUE(proto.max_skill_level >= 0 && proto.max_skill_level <= 50, "max_skill_level", proto.max_skill_level);
    CHECK_MAP_END()

    CHECK_MAP_BEGIN(BossLevel)
        CHECK_MAProto(Level, proto.prev_level, "prev_level");
        for (int i=0; i<3; ++i)
            CHECK_MAProto(Level, proto.boss[i], fmt_cstr("boss[%d]", i+1));
        CHECK_MAProto(Consume, proto.reset_consume, "reset_consume");
        CHECK_MAProto(Reward, proto.occupation_reward, "occupation_reward");
    CHECK_MAP_END()

    CHECK_ARR_BEGIN(Star)
        for (int i=0; i<proto.next_star_num; ++i) {
            CHECK_ARProto(Star, proto.next_star_proto[i], fmt_cstr("next_str_proto%d", i+1));
            if (proto.next_star_proto[i] >= 0)
                CHECK_NVALUE(proto.next_star_prob[i] >= 0, fmt_cstr("next_str_prob%d", i+1), proto.next_star_prob[i]);
        }

        CHECK_MAProto(Consume, proto.money_consumeid, "money_consumeid");
        CHECK_MAProto(Consume, proto.gamemoney_consumeid, "gamemoney_consumeid");
    CHECK_ARR_END()

//    CHECK_ARR_BEGIN()
//    CHECK_ARR_END()
//    CHECK_MAP_BEGIN()
//    CHECK_MAP_END()

    CHECK_MAP_BEGIN(Item)
        CHECK_NVALUE(proto.id >= 0, "protoid", proto.id);
        CHECK_NVALUE(EItemType_IsValid(proto.type) || proto.type < 0, "type", proto.type);
        CHECK_NVALUE(proto.price >= 0, "price", proto.price);
        CHECK_MAProto(Consume, proto.buy_consume, "buy_consume");
    CHECK_MAP_END()

    CHECK_ARR_BEGIN(EggRandom)
        for (int i=0; i<PetEggLevelEggNum; ++i)
            CHECK_MAProto(Item, proto.item_proto[i], fmt_cstr("item_protoid%d", i+1));
		CHECK_MAProto(Consume, proto.consume[0], "consume[0]");
		CHECK_MAProto(Consume, proto.consume[1], "consume[1]");
    CHECK_ARR_END()

    CHECK_ARR_BEGIN(Star)
        CHECK_NVALUE(proto.next_star_num > 0, "next_star_num", proto.next_star_num);
    CHECK_ARR_END()

    CHECK_ARR_BEGIN(SpriteQuality)
        for (int i=0; i<proto.sprite_protos.size(); ++i)
            CHECK_MAProto(Sprite, proto.sprite_protos[i], fmt_cstr("sprite_proto%d", i+1));
        for (int i=0; i<StarProtoNum; ++i)
            CHECK_NVALUE(proto.consume_star[i] >= 0, fmt_cstr("consume_star%d", i+1), proto.consume_star[i]);
    CHECK_ARR_END()

    CHECK_MAP_BEGIN(RandSet)
        int prob = 0;
        for (int i=0; i<proto.item_num; ++i) {
            if (proto.protoid[i] < 0)
                break;

            prob += proto.prob[i];
        }

        CHECK_NVALUE(prob == 10000, "sum_of_prob", prob);
    CHECK_MAP_END()

    CHECK_ARR_BEGIN(ComposeStone)
        CHECK_NVALUE(proto.id >= 0 && proto.id <=4, "id", proto.id);
        CHECK_NVALUE(proto.money_prob >= 0 && proto.money_prob <=10000, "money_prob", proto.money_prob);
        CHECK_NVALUE(proto.gamemoney_prob >= 0 && proto.gamemoney_prob <=10000, "gamemoney_prob", proto.gamemoney_prob);
        CHECK_MAProto(Consume, proto.money_consume, "money_consume");
        CHECK_MAProto(Consume, proto.gamemoney_consume, "gamemoney_consume");
        CHECK_MAProto(Item, proto.next_stone_protoid, "next_stone_protoid");
    CHECK_ARR_END()

    CHECK_ARR_BEGIN(PetFamily)
        CHECK_MAProto(RandSet, proto.compose_reward_skill_set, "compose_reward_skill_set");
    CHECK_ARR_END()

    CHECK_ARR_BEGIN(MagicLevel)
        CHECK_MAProto(RandSet, proto.compose_reward_magic_set, "compose_reward_magic_set");
    CHECK_ARR_END()

    CHECK_ARR_BEGIN(EquipLevel)
        CHECK_NVALUE(proto.id >= 0 && proto.id <= 4, "id", proto.id);
        CHECK_NVALUE(proto.levelup_consume.size() == PlayerEquipSlotNum, "levelup_consume_num", proto.levelup_consume.size());
        for (int i=0; i<proto.levelup_consume.size(); ++i)
            CHECK_MAProto(Consume, proto.levelup_consume[i], fmt_cstr("levelup_consume%d", i+1));

        CHECK_NVALUE(proto.enhance_max_num != 0 && proto.enhance_max_num == proto.enhance_consume.size(), "enhance_max_num", proto.enhance_max_num);
        CHECK_NVALUE(proto.enhance_base_num >= 0, "enhance_base_num", proto.enhance_base_num);

        for (int i=0; i<proto.enhance_max_num; ++i)
            CHECK_MAProto(Consume, proto.enhance_consume[i], fmt_cstr("enhance_consume%d", i+1));

        CHECK_NVALUE(proto.star_min_game_money >= 0, "star_min", proto.star_min_game_money);
        CHECK_NVALUE(proto.star_max_game_money >= 0, "star_max", proto.star_max_game_money);
        CHECK_NVALUE(proto.star_min_game_money >= 0, "star_min", proto.star_min_game_money);
        CHECK_NVALUE(proto.star_max_game_money >= 0, "star_max", proto.star_max_game_money);

        CHECK_MAProto(Consume, proto.star_money_consume, "star_money_consume");
        CHECK_MAProto(Consume, proto.star_game_money_consume, "star_game_money_consume");
    CHECK_ARR_END()

    CHECK_MAP_BEGIN(Task)
        CHECK_NVALUE(ETaskType_IsValid(proto.type), "type", proto.type);
        CHECK_NVALUE(proto.misc >= 0, "misc", proto.misc);
        CHECK_MAProto(Reward, proto.reward, "reward");
        CHECK_NVALUE(proto.page >= 0, "page", proto.page);
        CHECK_NVALUE(proto.slot >= 0, "slot", proto.slot);
    CHECK_MAP_END()

    CHECK_ARR_BEGIN(Alive)
        CHECK_NVALUE(EAliveType_IsValid(proto.type), "type", proto.type);
        CHECK_NVALUE(proto.count > 0, "count", proto.count);
    CHECK_ARR_END()

    CHECK_ARR_BEGIN(AliveReward)
        CHECK_NVALUE(proto.count > 0, "count", proto.count);
        CHECK_MAProto(Reward, proto.reward, "reward");
    CHECK_ARR_END()

    CHECK_ARR_BEGIN(MoneyGet)
        CHECK_NVALUE(proto.consume > 0, "consume", proto.consume);
        CHECK_NVALUE(proto.gain_min > 0, "gain_min", proto.gain_min);
        CHECK_NVALUE(proto.gain_max > proto.gain_min, "gain_max", proto.gain_max);
    CHECK_ARR_END()

    CHECK_ARR_BEGIN(AccChargeReward)
        CHECK_NVALUE(proto.fee > 0, "fee", proto.fee);
        CHECK_NVALUE(proto.type >= 0 && proto.type <= 1, "type", proto.type);
        CHECK_MAProto(Reward, proto.rewardid, "rewardid");
    CHECK_ARR_END()

    CHECK_MAP_BEGIN(Charge)
        CHECK_NVALUE(proto.money > 0, "money", proto.money);
    CHECK_MAP_END()

    CHECK_MAP_BEGIN(Level)
    	CHECK_ARProto(Medal, proto.medalid, "medalid");
		CHECK_ARProto(SpriteQuality, proto.sprite_quality, "sprite_quality");
		if (ESpriteQuality_IsValid(proto.sprite_quality)) {
			CHECK_NVALUE(proto.sprite_level > 0, "sprite_level", proto.sprite_level);
		}

		CHECK_FIELD(Reward, reward);
		CHECK_MAProto(Reward, proto.reward, "reward");
        for (int i=0; i<PlayerCombatCSlotNum; ++i)
            CHECK_MAProto(Pet, proto.pet_protoid[i], fmt_cstr("pet_protoid[%d]", i));

    CHECK_MAP_END()

	CHECK_ARR_BEGIN(TrainReward)
		CHECK_NVALUE(proto.exp >= 0, "exp", proto.exp);
    	CHECK_NVALUE(proto.gamemoney >= 0, "gamemoney", proto.gamemoney);
	CHECK_ARR_END()

	CHECK_ARR_BEGIN(Floor)
		CHECK_MAProto(Reward, proto.special_reward, "special_reward");
		CHECK_MAProto(Level, proto.levelid, "levelid");
		CHECK_MAProto(Consume, proto.jump_consume, "jump_consume");

	CHECK_ARR_END()

	CHECK_ARR_BEGIN(PetFriendStage)
		CHECK_NVALUE(proto.req_friendvalue >= 0, "req_friendvalue", proto.req_friendvalue);
		CHECK_MAProto(Consume, proto.wash_m_consumeid, "wash_m_consumeid");
		CHECK_MAProto(Consume, proto.wash_g_consumeid, "wash_g_consumeid");
		CHECK_MAProto(Consume, proto.feed_consumeid, "feed_consumeid");
		CHECK_MAProto(Consume, proto.next_consumeid, "next_consumeid");
		CHECK_MAProto(Consume, proto.tran_consumeid, "tran_consumeid");


		for (auto &itr : proto.g_randatts) {
			CHECK_NVALUE(itr.att >= 0 && itr.att <= 7, "att", itr.att);
			CHECK_NVALUE(itr.min >= 0, "pct_min", itr.min);
			CHECK_NVALUE(itr.max >= 0, "pct_max", itr.max);
			CHECK_NVALUE(itr.max >= itr.min, "pct_max >= pct_min", 0);
		}

		for (auto &itr : proto.m_randatts) {
			CHECK_NVALUE(itr.att >= 0 && itr.att <= 7, "att", itr.att);
			CHECK_NVALUE(itr.min >= 0, "pct_min", itr.min);
			CHECK_NVALUE(itr.max >= itr.min, "pct_max >= pct_min", 0);
		}
	CHECK_ARR_END()

	CHECK_ARR_BEGIN(SpriteFormLevel)
		CHECK_MAProto(Consume, proto.refresh_consume, "refresh_consume");
		CHECK_NVALUE(proto.levelup_anima >= 0, "levelup_anima", proto.levelup_anima);
		CHECK_NVALUE(proto.att_num >= 0, "att_num", proto.att_num);
		for (int i=0; i<15; ++i) {
			CHECK_NVALUE(proto.att_value[i] >= 0, fmt_cstr("att_value%d", i+1), proto.att_value[i]);
		}
	CHECK_ARR_END()

	CHECK_ARR_BEGIN(Pointrank)
		for (auto &itr : proto.rewards) {
			CHECK_NVALUE(std::get<0>(itr) <= std::get<1>(itr), "range_min", std::get<0>(itr));
			CHECK_NVALUE(std::get<0>(itr) <= std::get<1>(itr), "range_max", std::get<1>(itr));
			CHECK_MAProto(Reward, std::get<2>(itr), "reward");
		}
	CHECK_ARR_END()

	CHECK_ARR_BEGIN(CardReward)
		CHECK_MAProto(Reward, proto.reward, "rewardid");
		CHECK_NVALUE(proto.num >= 0, "num", proto.num);
	CHECK_ARR_END()

    return gok;

#undef CHECK_ARR_END
#undef CHECK_ARR_BEGIN
#undef CHECK_MAP_END
#undef CHECK_MAP_BEGIN
#undef CHECK_ARProto
#undef CHECK_MAProto
#undef CHECK_NVALUE
#undef CHECK_FVALUE
}

bool ProtoMgr::init() {
#define LOAD_MAP_BEGIN(name, file) \
    is_ok = load_map_one<tagProto##name>(_mapProto##name, #file, [this](tagProto##name &proto, const Json::Value &one, bool &insert)->bool{   \
        bool ok = true;
#define LOAD_MAP_END() \
        return ok;  \
    }) && is_ok;
#define LOAD_ARR_BEGIN(name, file) \
    is_ok = load_arr_one<tagProto##name>(_arrProto##name, #file, [this](tagProto##name &proto, const Json::Value &one)->bool{   \
        bool ok = true;
#define LOAD_ARR_END() \
        return ok;  \
    }) && is_ok;

    bool is_ok = true;

    // 4
    LOAD_MAP_BEGIN(Item, item.txt)
        proto.id = one.get("id", -1).asInt();

        proto.type = one.get("type", -1).asInt();
        proto.misc1 = one.get("misc1", -1).asInt();
        proto.misc2 = one.get("misc2", 0).asInt();
        proto.misc3 = one.get("misc3", 0).asInt();
        proto.overlap = one.get("overlap", 1).asInt();
        proto.price = one.get("price", 0).asInt();
        proto.buy_consume = one.get("buy_consume", -1).asInt();
    LOAD_MAP_END()

    LOAD_MAP_BEGIN(Character, character.txt)
        proto.id = one.get("id", -1).asInt();

        vector<double> factor;
        id_list<double>(one.get("factor", ""), factor);
        for (int i=0; i<CanSeePetAttNum; ++i)
            proto.factor[i] = factor[i];

        proto.random = one.get("random", 0).asInt();
        switch (proto.random) {
        case 0:
            break;
        case 1:
            g_protomgr->rand_characters.push_back(proto.id);
            break;
        case 2:
            g_protomgr->rand_characters_hatch.push_back(proto.id);
            g_protomgr->rand_characters.push_back(proto.id);
            break;
        }

    LOAD_MAP_END()

    LOAD_MAP_BEGIN(AttMod, attmod.txt)
        proto.id = one.get("id", -1).asInt();

        for (int i=0; i<4; ++i) {
            proto.att[i] = one.get(fmt_cstr("att%d", i+1), -1).asInt();
            proto.flat[i] = one.get(fmt_cstr("flat_mod%d", i+1), 0).asInt();
            proto.pct[i] = one.get(fmt_cstr("pct_mod%d", i+1), 0).asInt();
        }
    LOAD_MAP_END()

    LOAD_MAP_BEGIN(Value, value.txt)
        proto.id = one.get("id", -1).asInt();
        proto.who = one.get("who", 0).asInt();
        proto.att = one.get("att", -1).asInt();
        proto.pct = one.get("pct", 0).asInt();
        proto.damage = one.get("damage", 0).asInt() != 0;
    LOAD_MAP_END()

    LOAD_MAP_BEGIN(Buff, buff.txt)
        proto.id = one.get("id", -1).asInt();

        proto.overlap = one.get("overlap", 0).asInt() != 0;
        proto.round_num = one.get("round_num", 0).asInt();
        proto.attmodid = one.get("attmodid", -1).asInt();
        proto.immunity = one.get("immunity", 0).asInt() != 0;
        proto.dizzy = one.get("dizzy", 0).asInt() != 0;
        proto.dummy = one.get("dummy", 0).asInt() != 0;
        proto.frozen = one.get("frozen", 0).asInt() != 0;

        proto.effect_point = one.get("effect_point", -1).asInt();
        proto.damage_valueid = one.get("damage_valueid", -1).asInt();
        proto.heal_valueid = one.get("heal_valueid", -1).asInt();

        CHECK_FIELD(AttMod, attmodid);
        CHECK_FIELD(Value, damage_valueid);
        CHECK_FIELD(Value, heal_valueid);
    LOAD_MAP_END()


    LOAD_MAP_BEGIN(Skill, skill.txt)
        proto.id = one.get("id", -1).asInt();

        proto.family = one.get("family", -1).asInt();

        proto.point = one.get("point", -1).asInt();
        proto.prev_skillid = one.get("prev_skillid", -1).asInt();
        proto.prob = one.get("prob", 10000).asInt();
        proto.cast_num = one.get("cast_num", -1).asInt();
        proto.cast_round = one.get("cast_round", -1).asInt();

        proto.caster_hp_pct_low = one.get("caster_hp_pct_lower", -1).asInt();
        proto.caster_hp_pct_high = one.get("caster_hp_pct_upper", -1).asInt();
        proto.target_hp_pct_low = one.get("target_hp_pct_lower", -1).asInt();
        proto.target_hp_pct_high = one.get("target_hp_pct_upper", -1).asInt();

        proto.caster_attmodid = one.get("attacker_attmodid", -1).asInt();
        proto.caster_buffid = one.get("attacker_buffid", -1).asInt();
        proto.caster_act_num_chg = one.get("attacker_act_num_chg", 0).asInt();
        proto.caster_damage_valueid = one.get("attacker_damage_valueid", -1).asInt();
        proto.caster_heal_valueid = one.get("attacker_heal_valueid", -1).asInt();
        proto.caster_purge = one.get("attacker_purge", 0).asInt() != 0;

        proto.target_attmodid = one.get("target_attmodid", -1).asInt();
        proto.target_buffid = one.get("target_buffid", -1).asInt();
        proto.target_act_num_chg = one.get("target_act_num_chg", 0).asInt();
        proto.target_damage_valueid = one.get("target_damage_valueid", -1).asInt();
        proto.target_heal_valueid = one.get("target_heal_valueid", -1).asInt();
        proto.target_purge = one.get("target_purge", 0).asInt() != 0;

        CHECK_FIELD(AttMod, caster_attmodid);
        CHECK_FIELD(Buff, caster_buffid);
        CHECK_FIELD(Value, caster_damage_valueid);
        CHECK_FIELD(Value, caster_heal_valueid);

        CHECK_FIELD(AttMod, target_attmodid);
        CHECK_FIELD(Buff, target_buffid);
        CHECK_FIELD(Value, target_damage_valueid);
        CHECK_FIELD(Value, target_heal_valueid);
    LOAD_MAP_END()


    LOAD_MAP_BEGIN(SkillSet, skill_set.txt)
        proto.id = one.get("id", -1).asInt();
        for (int i=0; i<20; ++i) {
            int32_t skill = one.get(fmt_cstr("skill%d", i+1), -1).asInt();
            int32_t prob = one.get(fmt_cstr("prob%d", i+1), -1).asInt();
            if (prob < 0)
                break;
            proto.item.push_back(make_pair(skill, prob));
            if (skill >= 0 && NULL == MAProto(Skill, skill)) {
                UTIL_LOG(E, "tagProtoSkill:%d not exist", skill);
                ok = false;
            }
        }
    LOAD_MAP_END()

    LOAD_MAP_BEGIN(SpriteSkill, sprite_skill.txt)
        proto.id = one.get("id", -1).asInt();

        proto.point = one.get("point", -1).asInt();
        proto.self = one.get("self", 0).asInt() != 0;

        proto.att = one.get("att", -1).asInt();
        proto.init_pct = one.get("init_pct", -1).asInt();
        proto.inc_pct = one.get("inc_pct", -1).asInt();

        proto.init_heal = one.get("init_heal", -1).asInt();
        proto.inc_heal = one.get("inc_heal", -1).asInt();

        proto.init_damage = one.get("init_damage", -1).asInt();
        proto.inc_damage = one.get("inc_damage", -1).asInt();
    LOAD_MAP_END()

    LOAD_ARR_BEGIN(SpriteQuality, sprite_quality.txt)
        proto.id = one.get("id", -1).asInt();
        proto.factor1 = one.get("factor1", 0).asInt();
        proto.factor2 = one.get("factor2", 1).asInt();
        for (int i=0; i<StarProtoNum; ++i)
            proto.consume_star[i] = one.get(fmt_cstr("consume_star%d", i+1), 0).asInt();
    LOAD_ARR_END()

    LOAD_MAP_BEGIN(Sprite, sprite.txt)
        proto.id = one.get("id", -1).asInt();
        proto.quality = one.get("quality", -1).asInt();
        proto.max_skill_level = one.get("max_skill_level", -1).asInt();
        if (ESpriteQuality_IsValid(proto.quality)) {
            auto quality_proto = (tagProtoSpriteQuality*)ARProto(SpriteQuality, proto.quality);
            if (NULL == quality_proto) {
                UTIL_LOG(E, "need read sprite_quality.txt");
                ok = false;
            } else
                quality_proto->sprite_protos.push_back(proto.id);
        }

        for (int i=0; i<SpriteSkillNum; ++i)
            proto.skill[i] = one.get(fmt_cstr("skill%d", i+1), -1).asInt();
    LOAD_MAP_END()

    LOAD_MAP_BEGIN(Pet, pet.txt)
        proto.id = one.get("id", -1).asInt();
        proto.cardid = one.get("cardid", -1).asInt();

        proto.character = one.get("character", -1).asInt();
        proto.family = one.get("family", -1).asInt();
        proto.quality = one.get("quality", 0).asInt();
        proto.release_reward = one.get("release_reward", -1).asInt();
        proto.stage = one.get("stage", 1).asInt();
        proto.def_normalskill_num = one.get("def_normalskill_num", PetNormalSkillNum).asInt();
        proto.max_normalskill_num = one.get("max_normalskill_num", PetNormalSkillNum).asInt();
        proto.attmod = one.get("attmod", -1).asInt();

        proto.potent_point = one.get("potent_point", 0).asInt();
        proto.evolve_level = one.get("evolve_level", 9999).asInt();
        proto.evolve_to = one.get("evolve_to", -1).asInt();
        proto.evo_itemid = one.get("evo_itemid", -1).asInt();

        proto.mutate_family = one.get("mutate_family", -1).asInt();
        proto.mutate_prob = one.get("mutate_prob", 0).asInt();

        memset(proto.aptitude, 0, sizeof(proto.aptitude));
        vector<int32_t> temp_list;
        id_list(one.get("max_aptitude", ""), temp_list);
        for (int i=0; i<temp_list.size(); ++i)
            proto.aptitude[i] = temp_list[i];

        for (int i=0; i<2; ++i)
            proto.skill[i] = one.get(fmt_cstr("skill%d", i+1), -1).asInt();
        proto.skill_set = one.get("skill_set", -1).asInt();

        if (proto.evolve_to >= 0 && proto.evolve_to != proto.id) {
            if (map_pet_evofrom.count(proto.evolve_to) != 0) {
                UTIL_LOG(E, "pet:%d evofrom multi pet", proto.evolve_to);
                ok = false;
            } else {
                map_pet_evofrom[proto.evolve_to] = proto.id;
            }
        }

        CHECK_FIELD(Character, character);
        CHECK_FIELD(Skill, skill[0]);
        CHECK_FIELD(Skill, skill[1]);
        CHECK_FIELD(SkillSet, skill_set);
    LOAD_MAP_END()


    LOAD_MAP_BEGIN(Consume, consume.txt)
        proto.id = one.get("id", -1).asInt();
        proto.money = one.get("money", 0).asInt();
        proto.game_money = one.get("game_money", 0).asInt();
        proto.honor = one.get("honor", 0).asInt();
        proto.pearl = one.get("pearl", 0).asInt();

        for (int i=0; i<ConsumeItemTypeNum; ++i) {
            int32_t protoid = one.get(fmt_cstr("item%d", i+1), -1).asInt();
            int32_t num = one.get(fmt_cstr("item_num%d", i+1), 0).asInt();

            proto.item_proto[i] = protoid;
            proto.item_num[i] = num;

            if (protoid >= 0 && NULL == MAProto(Item, protoid)) {
                UTIL_LOG(E, "tagProtoItem:%d not exist", protoid);
                ok = false;
            }
            if (protoid >= 0 && num <= 0) {
                UTIL_LOG(E, "tagProtoItem:%d num:%d error", protoid, num);
                ok = false;
            }
        }
    LOAD_MAP_END()

    LOAD_MAP_BEGIN(Reward, reward.txt)
        proto.id = one.get("id", -1).asInt();


    	proto.pet_friprob = one.get("pet_friprob", 0).asInt();
        proto.pet_exp = one.get("pet_exp", 0).asInt();
        proto.money = one.get("money", 0).asInt();
        proto.game_money = one.get("game_money", 0).asInt();
        proto.honor = one.get("honor", 0).asInt();

        memset(proto.one_item_prob, -1, sizeof(proto.one_item_prob));
        memset(proto.one_item_proto, -1, sizeof(proto.one_item_proto));
        memset(proto.one_item_num, -1, sizeof(proto.one_item_num));

        memset(proto.many_item_prob, -1, sizeof(proto.many_item_prob));
        memset(proto.many_item_proto, -1, sizeof(proto.many_item_proto));
        memset(proto.many_item_num, -1, sizeof(proto.many_item_num));


        int32_t total_prob = 10000;
        int i=0;
        for (i=0; i<RewardOneItemTypeNum; ++i) {
            vector<int32_t> numbers;
            id_list(one.get(fmt_cstr("one_item%d", i+1), ""), numbers);

            if (numbers.empty() || numbers.size() != 3)
                break;

            int32_t protoid = numbers[0];
            int32_t num = numbers[1];
            int32_t prob = numbers[2];

            proto.one_item_proto[i] = protoid;
            proto.one_item_num[i] = num;
            proto.one_item_prob[i] = prob;
            total_prob -= prob;

            if (protoid >= 0 && NULL == MAProto(Item, protoid)) {
                UTIL_LOG(E, "tagProtoItem:%d not exist", protoid);
                ok = false;
            }
            if (protoid >= 0 && (num < 0 || prob <= 0)) {
                UTIL_LOG(E, "tagProtoItem:%d num:%d prob:%d error", protoid, num, prob);
                ok = false;
            }
        }
        if (total_prob > 0) {
        	proto.one_item_prob[i] = total_prob;
        }

        for (int i=0; i<RewardManyItemSlotNum; ++i) {
            int32_t total_prob = 10000;
            // to RewardManyItemTypeNum-1 because
            int j=0;
            for (; j<RewardManyItemTypeNum; ++j) {
                vector<int32_t> numbers;
                id_list(one.get(fmt_cstr("many_item%d_%d", i+1, j+1), ""), numbers);

                if (numbers.empty() || numbers.size() != 3)
                    break;

                int32_t protoid = numbers[0];
                int32_t num = numbers[1];
                int32_t prob = numbers[2];

                proto.many_item_proto[i][j] = protoid;
                proto.many_item_num[i][j] = num;
                proto.many_item_prob[i][j] = prob;
                total_prob -= prob;

                if (protoid >= 0 && NULL == MAProto(Item, protoid)) {
                    UTIL_LOG(E, "tagProtoItem:%d not exist", protoid);
                    ok = false;
                }
                if (protoid >= 0 && (num < 0 || prob <= 0)) {
                    UTIL_LOG(E, "tagProtoItem:%d num:%d prob:%d error", protoid, num, prob);
                    ok = false;
                }
            }
            if (total_prob > 0) {
           		proto.many_item_prob[i][j] = total_prob;
            }
        }
    LOAD_MAP_END()

    LOAD_MAP_BEGIN(Level, level.txt)
        proto.id = one.get("id", -1).asInt();

    	proto.medalid = one.get("medalid", -1).asInt();
        proto.level = one.get("level", 1).asInt();
        proto.random = one.get("random", 0).asInt();
        proto.sprite_quality = one.get("sprite_quality", -1).asInt();
        proto.sprite_level = one.get("sprite_level", -1).asInt();
        proto.reward = one.get("reward", -1).asInt();

        for (int i=0; i<PlayerCombatCSlotNum; ++i) {
            proto.pet_protoid[i] = one.get(fmt_cstr("pet_protoid%d", i+1), -1).asInt();
            vector<int32_t> lst;
            id_list(one.get(fmt_cstr("pet_atts%d", i+1), ""), lst);
            if (proto.pet_protoid[i] >= 0 && lst.size() != EPetAtt_ARRAYSIZE) {
                UTIL_LOG(E, "att num error");
                ok = false;
            }

            for (int j=0; j<EPetAtt_ARRAYSIZE; ++j) {
                if(j < int(lst.size())) {
                    if(0 == j) {
                        proto.pet_def_att[i][j] = lst[j] * 5;
                    } else if(1 == j) {
                        proto.pet_def_att[i][j] = lst[j];
                    } else {
                        proto.pet_def_att[i][j] = lst[j];
                    }
                } else {
                    proto.pet_def_att[i][j] = 0;
                }
            }

            id_list(one.get(fmt_cstr("pet_skill%d", i+1), ""), lst);
            for (int j=0; j<PetSpecSkillNum; ++j) {
                if (j < int(lst.size())) {
                    int32_t skill = lst[j];
                    proto.pet_skill[i][j] = skill;
                    if (skill >= 0 && NULL == MAProto(Skill, skill)) {
                        UTIL_LOG(E, "tagProtoSkill:%d not exist", skill);
                        ok = false;
                    }
                } else {
                    proto.pet_skill[i][j] = -1;
                }
            }
        }

    LOAD_MAP_END()

    LOAD_ARR_BEGIN(EquipLevel, equip_level.txt)
        proto.id = one.get("id", -1).asInt();

        id_list(one.get("levelup_consume", ""), proto.levelup_consume);
        proto.enhance_base_num = one.get("enhance_base_num", 0).asInt();
        proto.enhance_max_num = one.get("enhance_max_num", 0).asInt();
        id_list(one.get("enhance_consume", ""), proto.enhance_consume);

        proto.star_min_game_money = one.get("star_min_g", 0).asInt();
        proto.star_max_game_money = one.get("star_max_g", 0).asInt();
        proto.star_min_money = one.get("star_min_m", 0).asInt();
        proto.star_max_money = one.get("star_max_m", 0).asInt();
        proto.star_money_consume = one.get("star_money_consume", -1).asInt();
        proto.star_game_money_consume = one.get("star_game_money_consume", -1).asInt();
    LOAD_ARR_END()

    LOAD_MAP_BEGIN(BossLevel, boss_level.txt)
        proto.id = one.get("id", -1).asInt();
        proto.prev_level = one.get("prev_level", -1).asInt();
        proto.reset_consume = one.get("reset_consume", -1).asInt();
        for (int i=0; i<3; ++i)
            proto.boss[i] = one.get(fmt_cstr("boss%d", i+1), -1).asInt();

        proto.occupation_mins = one.get("occupation_mins", 60).asInt();
        proto.occupation_reward = one.get("occupation_reward", -1).asInt();
    LOAD_MAP_END()

    LOAD_MAP_BEGIN(Encounter, encounter.txt)
        proto.id = one.get("id", -1).asInt();
        proto.actnum_mod = one.get("actnum_mod", 0).asInt();
        proto.boss = one.get("boss", -1).asInt();
        proto.money = one.get("money", 0).asInt();

        CHECK_FIELD(Level, boss);
    LOAD_MAP_END()

    LOAD_MAP_BEGIN(EncounterItem, encounter_item.txt)
        proto.id = one.get("id", -1).asInt();
        proto.encounter = one.get("encounter", -1).asInt();
        proto.init_actnum_mod = one.get("init_actnum_mod", 0).asInt();
        proto.actnum_mod = one.get("actnum_mod", 0).asInt();
        proto.rate_effect = one.get("rate_effect", 1).asInt();
        proto.consume = one.get("consume", -1).asInt();

        CHECK_FIELD(Consume, consume);
    LOAD_MAP_END()

    LOAD_MAP_BEGIN(Explore, explore.txt)
        proto.id = one.get("id", -1).asInt();
        proto.prev_bosslevel = one.get("prev_bosslevel", -1).asInt();
        proto.init_actnum = one.get("init_actnum", 25).asInt();
        proto.enter_consume = one.get("enter_consume", -1).asInt();
        proto.reward = one.get("reward", -1).asInt();

        for (int i=0; i<12; ++i) {
            std::string encounter = one.get(fmt_cstr("encounter%d", i+1), "").asString();
            if (encounter.empty())
                continue;

            vector<string> dest;
            split(encounter, ",", dest);
            if (dest.size() != 2)
                continue;

            auto itr = dest.begin();
            int32_t encounterid = atoi(itr->c_str());
            ++itr;
            int32_t prob = atoi(itr->c_str());
            proto.encounter.emplace_back(encounterid, prob);

            auto encounter_proto = MAProto(Encounter, encounterid);
            if (encounterid >= 0 && NULL == encounter_proto) {
                UTIL_LOG(E, "tagProto%s:%d not exist", "Encounter", encounterid);
                ok = false;
            }
        }

        vector<int32_t> cards;
        id_list(one.get("mapcard", ""), proto.mapcard);

        CHECK_FIELD(Reward, reward);
        CHECK_FIELD(Consume, enter_consume);
    LOAD_MAP_END()

    LOAD_ARR_BEGIN(Medal, medal.txt)
        proto.id = one.get("id", -1).asInt();
        proto.maxpower_add = one.get("maxpower_add", 0).asInt();
        proto.group = one.get("group", -1).asInt();
        proto.attmod = one.get("attmod", -1).asInt();
        proto.task_page = one.get("task_page", 0).asInt();
    LOAD_ARR_END()

    LOAD_ARR_BEGIN(PetLevel, pet_level.txt)
        proto.id = one.get("id", -1).asInt();
        proto.levelup_exp_need = one.get("levelup_exp_need", 0).asInt();
        for (int i=0; i<EQuality_ARRAYSIZE; ++i)
            proto.release_reward[i] = one.get(fmt_cstr("release_reward%d", i+1), -1).asInt();

        CHECK_FIELD(Reward, release_reward[0]);
        CHECK_FIELD(Reward, release_reward[1]);
        CHECK_FIELD(Reward, release_reward[2]);
        CHECK_FIELD(Reward, release_reward[3]);
        CHECK_FIELD(Reward, release_reward[4]);
    LOAD_ARR_END()

    LOAD_ARR_BEGIN(PetRearConsume, pet_rear_consume.txt)
        proto.id = one.get("id", -1).asInt();
        proto.money_consume = one.get("money_consume", -1).asInt();
        proto.game_money_consume = one.get("game_money_consume", -1).asInt();
        CHECK_FIELD(Consume, money_consume);
        CHECK_FIELD(Consume, game_money_consume);
    LOAD_ARR_END()

    LOAD_ARR_BEGIN(PetQuality, pet_quality.txt)
        proto.id = one.get("id", -1).asInt();
        proto.qualityup_give_qexp = one.get("qualityup_give_qexp", 0).asInt();
        proto.qualityup_need_qexp = one.get("qualityup_need_qexp", 0).asInt();
    LOAD_ARR_END()

    LOAD_ARR_BEGIN(EggRandom, egg_random.txt)
        proto.id = one.get("id", -1).asInt();
		vector<int32_t> numbers;
		id_list(one.get("consume", ""), numbers);
        for (int i=0; i<cs::CEggRandom_ConsumeType_ConsumeType_ARRAYSIZE; ++i) {
        	if (i < numbers.size())
        		proto.consume[i] = numbers[i];
        	else
        		proto.consume[i] = -1;
        }

        for (int i=0; i<PetEggLevelEggNum; ++i) {
            int32_t item_prob = one.get(fmt_cstr("item_prob%d", i+1), 0).asInt();
            int32_t item_proto = one.get(fmt_cstr("item_proto%d", i+1), -1).asInt();
            proto.item_prob[i] = item_prob;
            proto.item_proto[i] = item_proto;
            if (item_proto >= 0 && NULL == MAProto(Item, item_proto)) {
                UTIL_LOG(E, "error item:%d in egg_random.txt", item_proto);
                ok = false;
            }
        }
    LOAD_ARR_END()

    LOAD_ARR_BEGIN(Star, star.txt)
        proto.id = one.get("id", -1).asInt();
        proto.anima_gain = one.get("anima_gain", 0).asInt();
        proto.money_consumeid = one.get("money_consumeid", 1).asInt();
        proto.gamemoney_consumeid = one.get("gamemoney_consumeid", 1).asInt();
        proto.next_star_num = 0;
        for (int i=0; i<6; ++i) {
            vector<int32_t> vec_stars;
            id_list(one.get(fmt_cstr("next_star%d", i+1), ""), vec_stars);
            if (vec_stars.empty())
                break;

            int32_t protoid = vec_stars[0];
            int32_t prob = vec_stars[1];
            proto.next_star_proto[i] = protoid;
            proto.next_star_prob[i] = prob;

            ++proto.next_star_num;
        }
    LOAD_ARR_END()

    LOAD_ARR_BEGIN(SpriteSkillLevel, sprite_skill_level.txt)
        proto.id = one.get("id", -1).asInt();
        for (int i=0; i<ESpriteQuality_ARRAYSIZE; ++i)
            proto.anima_consume[i] = one.get(fmt_cstr("anima_consume%d", i+1), 0).asInt();
    LOAD_ARR_END()

    LOAD_ARR_BEGIN(PetStar, pet_star.txt)
        proto.id = one.get("id", -1).asInt();
        proto.min_aptitude = one.get("min_aptitude", 100 * proto.id).asInt();
        proto.max_aptitude = one.get("max_aptitude", 100 * proto.id).asInt();
        proto.att_add = one.get("att_add", 100 * proto.id).asInt();
    LOAD_ARR_END()

    LOAD_MAP_BEGIN(RandSet, rand_set.txt)
        insert = false;

        proto.id = one.get("id", -1).asInt();
        if (proto.id < 0)
            return false;

        int32_t protoid = one.get("protoid", -1).asInt();
        int32_t prob = one.get("prob", 0).asInt();
        int32_t num = one.get("num", 0).asInt();
        if (protoid < 0 || prob <= 0 || num <= 0)
            return false;

        auto itr = this->_mapProtoRandSet.find(proto.id);
        tagProtoRandSet* pproto = NULL;
        if (itr == this->_mapProtoRandSet.end()) {
            itr = this->_mapProtoRandSet.emplace(proto.id, tagProtoRandSet()).first;
            pproto = &itr->second;
            pproto->item_num = 0;
            pproto->id = proto.id;
        } else {
            pproto = &itr->second;
        }

        if (NULL == pproto)
            return false;

        if (pproto->item_num >= 200)
            return false;

        pproto->protoid[pproto->item_num] = protoid;
        pproto->prob[pproto->item_num] = prob;
        pproto->num[pproto->item_num] = num;
        ++pproto->item_num;
    LOAD_MAP_END()

    LOAD_ARR_BEGIN(ComposeStone, compose_stone.txt)
        proto.id = one.get("id", -1).asInt();
        proto.money_prob = one.get("money_prob", 0).asInt();
        proto.gamemoney_prob = one.get("gamemoney_prob", 0).asInt();
        proto.money_consume = one.get("money_consume", -1).asInt();
        proto.gamemoney_consume = one.get("gamemoney_consume", -1).asInt();
        proto.next_stone_protoid = one.get("next_stone_protoid", -1).asInt();

    LOAD_ARR_END()

    LOAD_ARR_BEGIN(PetFamily, pet_family.txt)
        proto.id = one.get("id", -1).asInt();
        proto.compose_reward_skill_set = one.get("compose_reward_skill_set", -1).asInt();
    LOAD_ARR_END()

    LOAD_ARR_BEGIN(MagicLevel, magic_level.txt)
        proto.id = one.get("id", -1).asInt();
        proto.compose_reward_magic_set = one.get("compose_reward_magic_set", -1).asInt();
    LOAD_ARR_END()

    LOAD_ARR_BEGIN(ArenaReward, arena_reward.txt)
        proto.id = one.get("id", -1).asInt();
        proto.min = one.get("min", -1).asInt();
        proto.max = one.get("max", -1).asInt();
        proto.rewardid = one.get("rewardid", -1).asInt();
    LOAD_ARR_END()

    LOAD_MAP_BEGIN(Task, task.txt)
        proto.id = one.get("id", -1).asInt();
        proto.type = one.get("type", -1).asInt();
        proto.misc = one.get("misc", 0).asInt();
        proto.reward = one.get("reward", -1).asInt();
        proto.page = one.get("page", -1).asInt();
        proto.slot = one.get("slot", -1).asInt();
    	while (proto.page >= vec_page_task.size()) {
    		vec_page_task.push_back(vector<int32_t>());
    	}

    	if (proto.slot >= 3) {
    		UTIL_LOG(E, "task.txt id:%d slot:%d exceed", proto.id, proto.slot);
    		ok = false;
    	}

    	while (proto.slot >= vec_page_task[proto.page].size()) {
    		vec_page_task[proto.page].push_back(-1);
    	}
    	vec_page_task[proto.page][proto.slot] = proto.id;

    LOAD_MAP_END()

    LOAD_ARR_BEGIN(Alive, alive.txt)
        proto.id = one.get("id", -1).asInt();
        proto.type = one.get("type", -1).asInt();
        proto.count = one.get("count", 0).asInt();
        proto.alive_count = one.get("alive_count", 0).asInt();
    LOAD_ARR_END()

    LOAD_ARR_BEGIN(AliveReward, alive_reward.txt)
        proto.id = one.get("id", -1).asInt();
        proto.reward = one.get("reward", -1).asInt();
        proto.count = one.get("count", 0).asInt();
    LOAD_ARR_END()


    LOAD_ARR_BEGIN(MoneyGet, money_get.txt)
        proto.id = one.get("id", -1).asInt();
        proto.consume = one.get("consume", 0).asInt();
        proto.gain_min = one.get("gain_min", 0).asInt();
        proto.gain_max = one.get("gain_max", 0).asInt();
    LOAD_ARR_END()

    LOAD_MAP_BEGIN(Charge, charge.txt)
        proto.id = one.get("id", -1).asInt();
        proto.money = one.get("money", 0).asInt();
    LOAD_MAP_END()

    LOAD_ARR_BEGIN(AccChargeReward, acc_charge_reward.txt)
        proto.id = one.get("id", -1).asInt();
        proto.fee = one.get("fee", 0).asInt();
        proto.type = one.get("type", -1).asInt();
        proto.rewardid = one.get("rewardid", -1).asInt();
    LOAD_ARR_END()

	LOAD_ARR_BEGIN(WorldBossReward, worldboss_reward.txt)
		proto.id = one.get("id", -1).asInt();
		proto.min = one.get("min", -1).asInt();
		proto.max = one.get("max", -1).asInt();
		proto.rewardid = one.get("rewardid", -1).asInt();
	LOAD_ARR_END()

	LOAD_ARR_BEGIN(TrainReward, train_reward.txt)
		proto.id = one.get("id", -1).asInt();
		proto.exp = one.get("exp", 0).asInt();
		proto.gamemoney = one.get("gamemoney", 0).asInt();
	LOAD_ARR_END()

	LOAD_ARR_BEGIN(Floor, floor.txt)
		proto.id = one.get("id", -1).asInt();
		proto.special_reward = one.get("special_reward", -1).asInt();
		proto.levelid = one.get("levelid", -1).asInt();
		proto.jump_consume = one.get("jump_consume", -1).asInt();
	LOAD_ARR_END()

	LOAD_ARR_BEGIN(PetFriendStage, pet_friend_stage.txt)
		proto.id = one.get("id", -1).asInt();

		proto.req_friendvalue = one.get("req_friendvalue", 0).asInt();
		proto.wash_m_consumeid = one.get("wash_m_consumeid", -1).asInt();
		proto.wash_g_consumeid = one.get("wash_g_consumeid", -1).asInt();
		proto.feed_consumeid = one.get("feed_consumeid", -1).asInt();
		proto.next_consumeid = one.get("next_consumeid", -1).asInt();
		proto.tran_consumeid = one.get("tran_consumeid", -1).asInt();

        vector<int32_t> temp_list;
		tagProtoPetFriendStage::randatt_t att;
		for (int i=0; i<8; ++i) {
	        id_list(one.get(fmt_cstr("g_randatt%d", i+1), ""), temp_list);
			if (temp_list.size() != 3)
				break;

			att.att = temp_list[0];
			att.min = temp_list[1];
			att.max = temp_list[2];
			proto.g_randatts.push_back(att);
		}
		for (int i=0; i<8; ++i) {
	        id_list(one.get(fmt_cstr("m_randatt%d", i+1), ""), temp_list);
			if (temp_list.size() != 3)
				break;

			att.att = temp_list[0];
			att.min = temp_list[1];
			att.max = temp_list[2];
			proto.m_randatts.push_back(att);
		}
	LOAD_ARR_END()

	LOAD_ARR_BEGIN(SpriteFormLevel, sprite_form_level.txt)
		proto.id = one.get("id", -1).asInt();
		proto.levelup_anima = one.get("levelup_anima", 0).asInt();
		proto.refresh_consume = one.get("refresh_consume", -1).asInt();
		proto.att_num = one.get("att_num", 0).asInt();
		for (int i=0; i<15; ++i) {
			proto.att_value[i] = one.get(fmt_cstr("att_value%d", i+1), 0).asInt();
		}
	LOAD_ARR_END()

	LOAD_ARR_BEGIN(Pointrank, pointrank.txt)
		proto.id = one.get("id", -1).asInt();
		vector<int32_t> temp_list;
		for (int i=0; i<6; ++i) {
			id_list(one.get(fmt_cstr("range%d", i+1), ""), temp_list);
			if (temp_list.size() != 3) {
				ok = false;
				break;
			}
			proto.rewards.emplace_back(tuple<int32_t, int32_t, int32_t>(temp_list[0], temp_list[1], temp_list[2]));
		}
	LOAD_ARR_END()

	LOAD_ARR_BEGIN(CardReward, card_reward.txt)
		proto.id = one.get("id", -1).asInt();
		proto.num = one.get("num", 0).asInt();
		proto.reward = one.get("reward", -1).asInt();
	LOAD_ARR_END()


	UTIL_LOG(I, "ProtoMgr初始化结束");
    if (!is_ok)
        UTIL_LOG(E, "ProtoMgr初始化失败");

    return is_ok && check();

#undef LOAD_ARR_BEGIN
#undef LOAD_ARR_END
#undef LOAD_MAP_BEGIN
#undef LOAD_MAP_END
}
